#ifndef LASERKEYBOARD_H
#define LASERKEYBOARD_H

#include <QObject>
#include <QPlainTextEdit>
#include <QThread>
#include <opencv2/opencv.hpp>

#include <set>
#include <map>
#include <ctime>


//#define DEBUG_SHOW

#define QDEBUG_LOG
//#define STD_LOG

#define CORR_POS

#define CAM_WIDTH 1280
#define CAM_HEIGHT 720

#define AREA_GATE 40.0
#define PRESS_TIME_GATE 0.3
#define USE_UNDISTORT

typedef std::vector<cv::Point> Contour;
typedef std::vector<Contour> Contours;

/**
 * Cont: Struct of Contour with area
 *
 */
struct Cont{
    Contour cont;
    double area;
    Cont(const Contour &c): cont(c) {
        area = contourArea(c);
    }
    Cont(const Contour &c, double area): cont(c), area(area) {}
    Cont() {}
    /*
    friend bool operator <(const Cont& a, const Cont & b) {
        return a.area > b.area;
    }
    */
};

bool ContCmp(const Cont& a, const Cont & b);


class LaserKeyboard : public QThread
{
    Q_OBJECT

protected:
    void initKeyBoardMask();
    virtual void findTapPos(int CamIndex = 0);
    virtual int handleImg(cv::Mat &src, double fps = 0);

    bool isModifyKey(int key);
    void openImg(cv::Mat &src);


    cv::Point findLowestPoint(const Contour& cont);
    cv::Point3f getWorldPos(int u = 1564, int v = 762);

    const int modifyKeys[4] = {Qt::Key_Shift, Qt::Key_Control, Qt::Key_Alt, Qt::Key_Meta};

    static const cv::Point square_pts[4];

    cv::Mat KeyBoardMask, staMat, keyMap;
    QTextEdit* textEdit;
    std::set<int> pressedKeys;
    std::map<int, clock_t> pressedTime;
    Contours allTips;
    std::vector<int64> frameId;
    int64 totalFrame = 0;
public:
    explicit LaserKeyboard(QObject *parent = nullptr, QTextEdit* textEdit = nullptr);

    static  bool isInSquareMask(const cv::Point &p);
    void run();

signals:
    void countChanged(int count);
public slots:
};

#endif // LASERKEYBOARD_H
